
/*
  Copyright 2008-20011 Martin Koerner
  code [at] koerner-de.net
  http://code.google.com/p/printstring/



  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.






  PrintString: for string handling and manipulating

  PrintStringOF: PrintString + write into files or on stdout/stderr
  PrintStringIF: PrintString + read out files or stdin
  PrintStringFile: combines both PrintStringOF and PrintStringIF

  for automatic scanning of numbers in ascii files see PrintStringFile or PrintStringIF
*/


#ifndef PrintString_hpp_09238459z58294018i4
#define PrintString_hpp_09238459z58294018i4

#include <cstdlib>
#include <cstdio>
#include <cstring>

#include <iostream>
#include <sstream>
#include <fstream>

#include <exception>
#include <cstdarg>

//needed for file locking
#include <fcntl.h>

class PrintString
{
  public:
    PrintString(void);
    PrintString( const long anz);
    PrintString( const char* str);
    PrintString( const PrintString &str);
    PrintString( const std::string &str);
    
    virtual ~PrintString(void) {if (Str != (char*)0 ) delete [] Str;}
    
    
    char SetSize( const long anz) {Empty(); return Resize(anz, false);}
    char Resize( const long anz, const bool round_up=false);
    
    long GetLength(void) const {return Pos;}
    long Length(void) const {return Pos;}
    long length(void) const {return Pos;}
    long Len(void) const {return Pos;}
    
    char Empty(void) {Pos=0; if (Str!=(char*)0) Str[0] = 0; Internal_ResetLines(); return 0;}
    bool IsEmpty(void) const {if (Pos==0) return true; else return false;}
    

    char* GetCopyString(void) const;

    char* GetString(void) const {return Str;}
    char* c_str(void) const {return Str;}
    operator const char*(void) const {return (const char*) Str;}
    operator char*(void) const {return Str;}

    char Printf( const char *str, ...);
    char PPrintf( const char *str, ...);
    char EPrintf( const char *str, ...);
    
    long Scanf( const char *str, ...) const;


    char &operator [] ( const long p) const {return Str[p];}
    
    
    bool Compare( const char *str, const long modus=0) const;
    bool Compare( const PrintString &str, const long modus=0) const {if (Pos!=str.Len()) return false; return Compare( str, modus);}
    bool Compare( const std::string &str, const long modus=0) const {if (((unsigned long)Pos)!=str.length()) return false; return Compare( (const char*) str.c_str(), modus);}
    
    template <class STR>
    PrintString& operator = ( const STR &str) {Pos = 0; return *this << str;}
    PrintString& operator = ( const PrintString &str) {Pos = 0; return *this << str;}
    PrintString& operator = ( const std::string &str) {Pos = 0; return *this << str;}
    
    
    template <class STR>
    PrintString& operator += ( const STR &str) {return *this << str;}
    PrintString& operator += ( const PrintString &str) {return *this << str;}
    PrintString& operator += ( const std::string &str) {return *this << str;}
    
    template <class STR>
    PrintString& operator -= ( const STR &str) {Remove(str); return *this;}
    PrintString& operator -= ( const PrintString &str) {Remove(str); return *this;}
    PrintString& operator -= ( const std::string &str) {Remove(str); return *this;}
    
    
    PrintString& operator << ( const char *str);
    PrintString& operator << ( const PrintString &str);
    PrintString& operator << ( const std::string &str);
    
    
    PrintString& operator << ( const float val) {return *this << (double) val;}
    PrintString& operator << ( const double val);
    PrintString& operator << ( const long double val);

    PrintString& operator << ( const bool val);
    
    PrintString& operator << ( const char val) {return *this << (long) val;}
    PrintString& operator << ( const short val) {return *this << (long) val;}
    PrintString& operator << ( const int val) {return *this << (long) val;}
    PrintString& operator << ( const long val);
    
    PrintString& operator << ( const unsigned char val) {return *this << (unsigned long) val;}
    PrintString& operator << ( const unsigned short val) {return *this << (unsigned long) val;}
    PrintString& operator << ( const unsigned int val) {return *this << (unsigned long) val;}
    PrintString& operator << ( const unsigned long val);
    
    
    static const long First = 0;
    static const long Begin = 0;
    static const long Last = 1;
    static const long End = 1;
    
    // Needed in future for function Compare
    //static const long IgnoreCase = 1;
    //static const long IgnoreCarriageReturn = 2;

    
    

    char PutChar(const char val, const long num=1, const long index=0, const long from=End);
    char RemoveChar( const char val) {return Remove( val);}

    char Remove( const char val);
    char Remove( const char *str);
    char Remove( const PrintString &str) {if (str.Len()==0) return 0; else return Remove( str.c_str());}
    char Remove( const std::string &str) {if (str.length()==0) return 0; else return Remove( str.c_str());}
    
    char Remove( const long from, const long to) {if (to<from) return Internal_Shift(from,to-from); else return Internal_Shift(to,from-to);}
    
    
    char ReplaceChar( const char val1, const char val2) {return Replace( val1, val2);}
    char Replace( const char val1, const char val2) {for (long i=0;i<Pos;i++) {if (Str[i]==val1) Str[i]=val2;} return 0;}
    
    char Replace( const char *val1, const char *val2);
    
    char Replace( const PrintString &val1, const PrintString &val2) {return Replace( val1.c_str(), val2.c_str());}
    char Replace( const PrintString &val1, const char *val2) {return Replace( val1.c_str(), val2);}
    char Replace( const char *val1, const PrintString &val2) {return Replace( val1, val2.c_str());}
    
    char Replace( const std::string &val1, const std::string &val2) {return Replace( val1.c_str(), val2.c_str());}
    char Replace( const std::string &val1, const char *val2) {return Replace( val1.c_str(), val2);}
    char Replace( const char *val1, const std::string &val2) {return Replace( val1, val2.c_str());}
    
    

    long Find( const char val, const long num = 1, const long from = First, const long offset = 0) const;
    long Find( const char* str, const long num = 1, const long from = First, const long offset = 0) const;
    long Find( const PrintString &str, const long num = 1, const long from = First, const long offset = 0) const {return Find( str.c_str(), num, from, offset);}
    long Find( const std::string &str, const long num = 1, const long from = First, const long offset = 0) const {return Find( str.c_str(), num, from, offset);}


    long Count( const char val, const long from = First, const long offset=0) const;
    long Count( const char* str, const long from = First, const long offset=0) const;
    long Count( const PrintString &str, const long from = First, const long offset=0) const {return Count( str.c_str(), from, offset);}
    long Count( const std::string &str, const long from = First, const long offset=0) const {return Count( str.c_str(), from, offset);}


    char Truncate(const long pos, const long what=Last);




    long GetNumberOfLines(void);
    long GetNumberOfLinesConst(void) const;

    long Line2Index( const long line) const;
    long Index2Line( const long pos) const;


    char GetLine( PrintString &str, const long line=0);
    char GetLineConst( PrintString &str, const long line=0) const;
    char GetNextLine( PrintString &str) {return GetLine( str, LineIndex+1);}

    char RemoveLine( const long line);
    
    char ReplaceLine( const char* str, const long line=0);
    char ReplaceLine( const std::string &str, const long line=0) {return ReplaceLine( str.c_str(), line);}
    char ReplaceLine( const PrintString &str, const long line=0) {return ReplaceLine( str.c_str(), line);}
    
    
  protected:
    
    
    PrintString& Internal_Append( const char *str, const long length);

    void Internal_Init( const long anz);

    static char Internal_Copy( char* to, const char* from, const long len);

    char Internal_Printf(const char *str, va_list arg);

    char Internal_Shift( const long index, const long shift);
    
    void Internal_ResetLines(void) {LinePos=0; LineIndex=0; LineNum=0;}

    char *Str;
    long Anz;
    long Pos;

    long LinePos;
    long LineIndex;
    long LineNum;
};




inline bool operator == ( const PrintString &str1, const PrintString &str2) {return str1.Compare(str2);}
inline bool operator == ( const PrintString &str1, const std::string &str2) {return str1.Compare(str2);}
inline bool operator == ( const PrintString &str1, const char* str2) {return str1.Compare(str2);}
inline bool operator == ( const std::string &str2, const PrintString &str1) {return str1.Compare(str2);}
inline bool operator == ( const char* str2, const PrintString &str1) {return str1.Compare(str2);}


inline bool operator != ( const PrintString &str1, const PrintString &str2) {return !str1.Compare(str2);}
inline bool operator != ( const PrintString &str1, const std::string &str2) {return !str1.Compare(str2);}
inline bool operator != ( const PrintString &str1, const char* str2) {return !str1.Compare(str2);}
inline bool operator != ( const std::string &str2, const PrintString &str1) {return !str1.Compare(str2);}
inline bool operator != ( const char* str2, const PrintString &str1) {return !str1.Compare(str2);}


PrintString operator+ (const PrintString &str1, const PrintString&str2);
PrintString operator+ (const PrintString &str1, const char *str2);
PrintString operator+ (const char* str1, const PrintString &str2);
PrintString operator+ (const PrintString &str1, const std::string &str);
PrintString operator+ (const std::string &str, const PrintString &str2);


PrintString operator- (const PrintString &str1, const PrintString &str2);
PrintString operator- (const PrintString &str1, const char *str2);
PrintString operator- (const char* str1, const PrintString &str2);
PrintString operator- (const PrintString &str1, const std::string &str);
PrintString operator- (const std::string &str, const PrintString &str2);











// ###############   File Handling #####################


// virtual class for file

class PrintStringFileVirtual : public PrintString
{
  public:
    PrintStringFileVirtual(void) : PrintString(), Error(256), FileName(256)  {FirstInit();}
    PrintStringFileVirtual( const long anz) :  PrintString(anz), Error(256), FileName(256) {FirstInit();}
    PrintStringFileVirtual( const char* str) : PrintString( str), Error(256), FileName(256) {FirstInit();}
    PrintStringFileVirtual( const PrintString &str) : PrintString( str), Error(256), FileName(256) {FirstInit();}
    PrintStringFileVirtual( const std::string &str) : PrintString( str), Error(256), FileName(256) {FirstInit();}

    virtual ~PrintStringFileVirtual(void) {FreeLock();}
    
    
    char SetFileHandler( FILE* handler) {InitAllEmpty(); FILE_Handler = handler; return 0;}
    char SetFileHandler( std::fstream* handler) {InitAllEmpty(); fstream_Handler = handler; return 0;}

    char SetFileName( const char* name) {InitAllEmpty(); FileName = name; return 0;}
    char SetFileName( const PrintString &name) {InitAllEmpty(); FileName = name; return 0;}
    char SetFileName( const std::string &name) {InitAllEmpty(); FileName = name; return 0;}
    
    
    char *GetFileName(void) const {if (FileName.IsEmpty()) return (char*)0; else return FileName.c_str();}
    
    char SetWriteProtection( const bool val=true) {WriteProtection=val; return 0;}
    

    char ClearFile(void) {return ClearFile( FileName.c_str());}
    char ClearFile(const char* str);
    char ClearFile(const PrintString &str) {return ClearFile( str.c_str());}
    char ClearFile(const std::string &str) {return ClearFile( str.c_str());}

    char RemoveFile(void) {return RemoveFile( FileName.c_str());}
    char RemoveFile(const char* str);
    char RemoveFile(const PrintString &str) {return RemoveFile( str.c_str());}
    char RemoveFile(const std::string &str) {return RemoveFile( str.c_str());}

    char TouchFile(void) {return TouchFile( FileName.c_str());}
    char TouchFile(const char* str);
    char TouchFile(const PrintString &str) {return TouchFile( str.c_str());}
    char TouchFile(const std::string &str) {return TouchFile( str.c_str());}

    bool FileExist(void) {return FileExist( FileName.c_str());}
    bool FileExist(const char *str);
    bool FileExist(const PrintString &str) {return FileExist( str.c_str());}
    bool FileExist(const std::string &str) {return FileExist( str.c_str());}
    
    
    char UseLock( const bool val=true) {LockFile=val; TryLockFile=false; return 0;}
    char UseTryLock( const bool val=true) {LockFile=false; TryLockFile=val; return 0;}
    
    

    const char* GetError() {return Error;}
    bool Fail(void) {return IsFailed;}
    char UnFail(void) {IsFailed = false; return Error.Empty();}
    
  protected:

    PrintString Error;
    
    bool LockFile, TryLockFile;
    int LockID;
    
    char GetLock(void);
    char FreeLock(void);
    
    void InitAllEmpty(void);
    
    bool IsFailed;
    bool WriteProtection;
    
    FILE *FILE_Handler;
    std::fstream *fstream_Handler;
    PrintString FileName;
    
  private:
    void FirstInit(void) {InitAllEmpty(); LockFile=false; TryLockFile=false; LockID=0;}
};






// class for input



class PrintStringIF : virtual public PrintStringFileVirtual
{
  public:
    PrintStringIF(void) : PrintStringFileVirtual() {DataD=(double*)0;DataL=(long*)0; Columns=0; Lines=0;}
    PrintStringIF( const long anz) : PrintStringFileVirtual( anz) {DataD=(double*)0;DataL=(long*)0; Columns=0; Lines=0;}
    PrintStringIF( const char* str) : PrintStringFileVirtual( str) {DataD=(double*)0;DataL=(long*)0; Columns=0; Lines=0;}
    PrintStringIF( const PrintString &str) : PrintStringFileVirtual( str) {DataD=(double*)0;DataL=(long*)0; Columns=0; Lines=0;}
    PrintStringIF( const std::string &str) : PrintStringFileVirtual( str) {DataD=(double*)0;DataL=(long*)0; Columns=0; Lines=0;}
    
    virtual ~PrintStringIF(void) {if (DataD!=(double*)0) delete [] DataD;if (DataL!=(long*)0) delete [] DataL;}
    
    //musst declared once again, templates of assignment operators are not inherited
    template <class STR>
    PrintString& operator = ( const STR str) {Pos = 0; return *this << str;}
    
    char ReadFile(void) {return ReadIn();}
    char ReadStdIn(void) {return ReadIn(stdin);}
    
    template <class T>
    char ReadFile( const T file_name) {if (char ret = SetFileName( file_name)) return ret; return ReadIn();}
    
    char EReadFile(void) {Empty(); return ReadIn();}
    char EReadStdIn(void) {Empty(); return ReadIn(stdin);}
    
    template <class T>
    char EReadFile( const T file_name) {if (char ret = SetFileName( file_name)) return ret; Empty(); return ReadIn();}
    
    
    char ExtractData(bool use_long=false);
    char ExtractDataLong(void) {return ExtractData(true);}
    
    double *GetData(void) const {return DataD;}
    long *GetDataLong(void) const {return DataL;}
    
    long GetM(void) const {return Lines;}
    long GetN(void) const {return Columns;}
    
    
  protected:
    char ReadIn(void);
    char ReadIn( FILE *datei);
    char ReadIn( std::fstream *datei);
    
    double *DataD;
    long *DataL;
    long Columns, Lines;
};




// class for output

class PrintStringOF : virtual public PrintStringFileVirtual
{
  public:
    PrintStringOF(void) : PrintStringFileVirtual() {DeleteAfterFlush=true;}
    PrintStringOF( const long anz) : PrintStringFileVirtual( anz) {DeleteAfterFlush=true;}
    PrintStringOF( const char* str) : PrintStringFileVirtual( str) {DeleteAfterFlush=true;}
    PrintStringOF( const PrintString &str) : PrintStringFileVirtual( str) {DeleteAfterFlush=true;}
    PrintStringOF( const std::string &str) : PrintStringFileVirtual( str) {DeleteAfterFlush=true;}
    
    virtual ~PrintStringOF(void) {FlushOut();}
    
    //musst declared once again, templates of assignment operators are not inherited
    template <class STR>
    PrintString& operator = ( const STR str) {Pos = 0; return *this << str;}
    
    char HoldContent( const bool val=true) {DeleteAfterFlush=!val; return 0;}
    
    char FlushOut(void);
    char FlushStdOut(void);
    char FlushStdError(void);
    
    template <class file>
    char FlushOut( const file file_name) {if (char ret = SetFileName( file_name)) return ret; if (char ret = WriteOut()) return ret; if (DeleteAfterFlush) Empty(); return 0;}
    
  protected:
    
    char WriteOut(void);
    char WriteOut( FILE *datei);
    char WriteOut( std::fstream *datei);
    
    bool DeleteAfterFlush;
};










// Combining in and output class

class PrintStringFile : virtual public PrintStringOF, virtual public PrintStringIF
{
  public:
    PrintStringFile(void) : PrintStringFileVirtual(), PrintStringOF(), PrintStringIF() {}
    PrintStringFile( const long anz) : PrintStringFileVirtual( anz), PrintStringOF( anz), PrintStringIF( anz) {}
    PrintStringFile( const char* str) : PrintStringFileVirtual( str), PrintStringOF( str), PrintStringIF( str) {}
    PrintStringFile( const PrintString &str) : PrintStringFileVirtual( str), PrintStringOF( str), PrintStringIF( str) {}
    PrintStringFile( const std::string &str) : PrintStringFileVirtual( str), PrintStringOF( str), PrintStringIF( str) {}
    
    //musst declared once again, templates of assignment operators are not inherited
    template <class STR>
    PrintString& operator = ( const STR str) {Pos = 0; return *this << str;}
    
    ~PrintStringFile(void) {}
};


#endif /*PrintString_09238459z58294018i4*/
